﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using PlayerIO.GameLibrary;
using System.Drawing;
using System.Runtime.InteropServices;

namespace MyGame {
    /// <summary>
    /// This class represents a player
    /// </summary>
    public class Player : BasePlayer
    {
        /// <summary>
        /// 
        /// </summary>
        public string Name;
    }
    /// <summary>
    /// This class represents a specific game with 3 players
    /// </summary>
    [RoomType("Triviador")]
	public class GameCode : Game<Player> {
        private Boolean respuestasCompletasEvaluadas = false;
        private int contador = 0;
        /// <summary>
        /// variable that stores the number of responses given.
        /// </summary>
        private int respuestasDadas = 0;
        /// <summary>
        /// variable that stores the number of correctly responses given.
        /// </summary>
        private int respuestasCorrectas = 0;
        /// <summary>
        /// variable that stores the information of the player who responding questions has the first place
        /// </summary>
        Player p1 = new Player();
        /// <summary>
        /// variable that stores the information of the player who responding questions has the second place
        /// </summary>
        Player p2 = new Player();
        /// <summary>
        /// variable that stores the information of the player who responding questions has the thirth place
        /// </summary>
        Player p3 = new Player();
        int difJ1 = 0;
        int difJ2 = 0;
        int difJ3 = 0;
        Player j1 = new Player();
        Player j2 = new Player();
        Player j3 = new Player();
        int respuestasMalas = 0;
        int cantidadJugadores = 0;
        int idUsuario2 = 0; //Este usuario ganó 2 territorios
        int idUsuario1 = 0;//Este usuario ganó 1 territorios
        int idUsuario0 = 0;//Este usuario ganó 0 territorios
        Random random = new Random();
        /// <summary>
        /// variable that stores the information of the 1st player
        /// </summary>
        Player jugador1 = new Player();
        /// <summary>
        /// variable that stores the information of the 2nd player
        /// </summary>
        Player jugador2 = new Player();
        /// <summary>
        /// variable that stores the information of the 3th player
        /// </summary>
        Player jugador3 = new Player();
        /// <summary>
        /// variable that stores the base of the player 1.
        /// </summary>
        int baseJugador1 = 0;
        /// <summary>
        /// variable that stores the base of the player 2.
        /// </summary>
        int baseJugador2 = 0;
        /// <summary>
        /// variable that stores the base of the player 3.
        /// </summary>
        int baseJugador3 = 0;
        /// <summary>
        /// variable that stores the bases that ar not assigned yet.
        /// </summary>
        private List<int> baseAasignar;
        /// <summary>
        /// Indica la fase en que se encuentra el juego
        /// Fase 0: Asignacion bases
        /// Fase 1: Conquista
        /// Fase 2: Batalla
        /// Fase 3: Resultados
        /// </summary>
        private int fase = -1;
        /// <summary>
        /// This method is called when an instance of the game is created
        /// </summary>
		public override void GameStarted() {
            // anything you write to the Console will show up in the 
			// output window of the development server
			Console.WriteLine("Game is started: " + RoomId);
			// This is how you setup a timer
			// Sometimes, it can be very usefull to have a graphical representation
			// of the state of your game.
			// An easy way to accomplish this is to setup a timer to update the
			// debug view every 250th second (4 times a second).
			AddTimer(delegate {
				// This will cause the GenerateDebugImage() method to be called
				// so you can draw a grapical version of the game state.
				RefreshDebugView(); 
			}, 100);
		}
        /// <summary>
        /// This method is called when the last player leaves the room, and it's closed down.
        /// </summary>
		public override void GameClosed() {
			Console.WriteLine("RoomId: " + RoomId);
		}
		/// <summary>
        /// This method is called whenever a player joins the game, if the player joins the game but there are other 3 players
        /// the last player is not acepted. When a player joins the game, the server send an advertising to the other players
        /// (if any). When the 3th player joins the game, the server choose the bases of each player.
		/// </summary>
		/// <param name="player">
        /// "player" is the client that join a game
        /// </param>
		public override void UserJoined(Player player) {
			// this is how you send a player a message
            if (player.Id == 1)
            {
                jugador1 = player;
                cantidadJugadores++;
            }
            if (player.Id == 2)
            {
                jugador2 = player;
                cantidadJugadores++;
            }
            if (player.Id == 3)
            {
                jugador3 = player;
                cantidadJugadores++;
                
            }
            if (player.Id >= 4)
            {
                player.Disconnect();
                
            }
            Message m = Message.Create("ChatInit");
            m.Add(player.Id);
            foreach (Player p in Players)
            {
                m.Add(p.Id, p.ConnectUserId);
            }
            player.Send(m);
            Broadcast("ChatJoin", player.Id, player.ConnectUserId);
           
			// this is how you broadcast a message to all players connected to the game
			Broadcast("UserJoined", player.Id); 
            if (cantidadJugadores == 3)
            {
                this.Visible = false;
                Console.WriteLine("Jugadores completos, iniciando partida...");
                fase++;
                baseAasignar = new List<int>();
                baseAasignar.Add(1);
                baseAasignar.Add(2);
                baseAasignar.Add(3);
                baseAasignar.Add(4);
                baseAasignar.Add(5);
                baseAasignar.Add(6);
                baseAasignar.Add(7);
                baseAasignar.Add(8);
                baseAasignar.Add(9);
                baseAasignar.Add(10);
                baseAasignar.Add(11);
                baseAasignar.Add(12);
                baseAasignar.Add(13);
                baseAasignar.Add(14);
                baseAasignar.Add(15);
                int aux = (numeroAleatoreo(14, random));
                
                baseJugador1 = baseAasignar[aux];
                baseAasignar.RemoveAt(aux);
                aux = (numeroAleatoreo(13, new Random(aux)));
                
                baseJugador2 = baseAasignar[aux];
                baseAasignar.RemoveAt(aux);
                random = new Random(aux);
                aux = (numeroAleatoreo(12,random));
                
                baseJugador3 = baseAasignar[aux];
                Console.WriteLine("Base jugador 1 " + baseJugador1);
                Console.WriteLine("Base jugador 2 " + baseJugador2);
                Console.WriteLine("Base jugador 3 " + baseJugador3);
                
                jugador1.Send("jugadoresCompletos", baseJugador1, baseJugador2, baseJugador3, jugador1.Id);
                jugador2.Send("jugadoresCompletos", baseJugador1, baseJugador2, baseJugador3, jugador2.Id);
                jugador3.Send("jugadoresCompletos", baseJugador1, baseJugador2, baseJugador3, jugador3.Id);
                fase++;

            }
		}
        /// <summary>
        /// This method is called when a player leaves the game, the server send a broadcast message with the player
        /// that leaves the game.
        /// </summary>
        /// <param name="player">
        /// "player" is the player that leaves the game
        /// </param>
		public override void UserLeft(Player player) {
			Broadcast("UserLeft", player.Id);
            Broadcast("ChatLeft", player.Id);
            Console.WriteLine("User left the chat " + player.Id);
            contador--;
		}
        /// <summary>
        /// This method is called when a player sends a message into the server code
        /// </summary>
        /// <param name="player">
        /// "player" is the player that sends a message to the server.
        /// </param>
        /// <param name="message">
        /// "message" is the message to the server.
        /// </param>
        public override void GotMessage(Player player, Message message)
        {
            switch (message.Type)
            {
                // This is how you would set a players name when they send in their name in a 
                // "MyNameIs" message
                case "MyNameIs":
                    {
                        if (player.Id == 1)
                        jugador1.Name = message.GetString(0);
                        if (player.Id == 2)
                        jugador2.Name = message.GetString(0);
                        if (player.Id == 3)
                        {
                            jugador3.Name = message.GetString(0);
                            Broadcast("Nombres", jugador1.Name, jugador2.Name, jugador3.Name); 
                        }
                    }
                    break;
                // En este método se envia un mensaje a los demás usuarios cuando uno de estos elige las preguntas abiertas o cerradas
                case "preguntaAbierta":
                    {
                        if (player.Id == 1)
                        {
                            Console.WriteLine("Id del jugador que solicita la pregunta abierta para todos: " + player.Id);
                            int numero = numeroAleatoreo(29, new Random()) + 1;
                            Console.WriteLine("Numero de pregunta abierta elegida: " + numero);
                            Broadcast("preguntaAbierta", numero);
                        }
                    }
                    break;
                case "ChatMessage":
                    {
                        Broadcast("ChatMessage", player.Id, message.GetString(0));
                    }
                    break;
                case "preguntaCerrada":
                    {
                        int numero = numeroAleatoreo(29, new Random());
                        numero++;
                        Broadcast("preguntaCerrada", numero);
                    }
                break;
                case "Win":
                    {
                        respuestasCorrectas++;
                        respuestasDadas++;
                            if (respuestasCorrectas == 1)
                            {
                                p1 = player;
                            }
                            if (respuestasCorrectas == 2)
                            {
                                p2 = player;
                            }
                            if (respuestasCorrectas == 3)
                            {
                                p3 = player;
                            }
                            if (respuestasDadas == 3)
                            {
                                if (!respuestasCompletasEvaluadas)
                                {
                                    if (respuestasCorrectas == 1)
                                    {
                                        if (fase == 1)
                                        {
                                            p1.Send("Win",2);
                                            idUsuario2 = p1.Id;
                                            if (difJ1 < difJ2)
                                            {
                                                j1.Send("Win",1);
                                                idUsuario1 = j1.Id;
                                                j2.Send("Lose",0);
                                                idUsuario0 = j2.Id;
                                            }
                                            else if (difJ2 > difJ1)
                                            {
                                                j2.Send("Win",1);
                                                idUsuario1 = j2.Id;
                                                j1.Send("Lose",0);
                                                idUsuario0 = j1.Id;
                                            }
                                            else if (difJ2 == difJ1)
                                            {
                                                if (numeroAleatoreo(1, random) == 1)
                                                {
                                                    j1.Send("Win",1);
                                                    idUsuario1 = j1.Id;
                                                    j2.Send("Lose",0);
                                                    idUsuario0 = j2.Id;
                                                }
                                                else
                                                {
                                                    j2.Send("Win",1);
                                                    idUsuario1 = j2.Id;
                                                    j1.Send("Lose",0);
                                                    idUsuario0 = j1.Id;
                                                }
                                            }
                                        }
                                        if (fase == 2)
                                        {
                                            p1.Send("Win");
                                            j1.Send("Win");
                                            j2.Send("Lose");
                                        }
                                    }
                                    if (respuestasCorrectas == 2)
                                    {
                                        if (fase == 1)
                                        {
                                            p1.Send("Win",2);
                                            idUsuario2 = p1.Id;
                                            p2.Send("Win",1);
                                            idUsuario1 = p2.Id;
                                            j1.Send("Lose",0);
                                            idUsuario0 = j1.Id;
                                        }
                                        if (fase == 2)
                                        {
                                            p1.Send("Win");
                                            p2.Send("Lose");
                                            j1.Send("Lose");
                                        }
                                    }
                                    if (respuestasCorrectas == 3)
                                    {
                                        if (fase == 1)
                                        {
                                            p1.Send("Win",2);
                                            idUsuario2 = p1.Id;
                                            p2.Send("Win",1);
                                            idUsuario1 = p2.Id;
                                            p3.Send("Lose",0);
                                            idUsuario0 = p3.Id;
                                        }
                                        if (fase == 2)
                                        {
                                            p1.Send("Win");
                                            p2.Send("Lose");
                                            p3.Send("Lose");
                                        }
                                    }
                                    Console.WriteLine("Restarting game");
                                    Broadcast("Restart");
                                    Console.WriteLine("Broadcast Restart finished");
                                    respuestasCorrectas = 0;
                                    respuestasDadas = 0;
                                    respuestasMalas = 0;
                                    respuestasCompletasEvaluadas = true;

                                }
                            }
                    }
                break;
                case "Disconnect":
                {
                    player.Send("deleteChat");
                    player.Disconnect();
                    
                }
                break;
                case "WinPregCerradas":
                    {
                        respuestasDadas++;
                        respuestasCorrectas++;
                        if (respuestasCorrectas == 1)
                        {
                            p1 = player;
                        }
                        if (respuestasCorrectas == 2)
                        {
                            p2 = player;
                        }
                        if (respuestasCorrectas == 3)
                        {
                            p3 = player;
                        }
                        if (respuestasDadas == 3)
                        {
                            if (respuestasCorrectas == 1)
                            {
                                p1.Send("Win");
                            }
                            if (respuestasCorrectas == 2)
                            {
                                p1.Send("Win");
                                p2.Send("Win");
                            }
                            if (respuestasCorrectas == 3)
                            {
                                p1.Send("Win");
                                p2.Send("Win");
                                p3.Send("Win");
                            }
                            Console.WriteLine("Restarting game");
                            Broadcast("Restart");
                            Console.WriteLine("Broadcast Restart finished");
                            respuestasCorrectas = 0;
                            respuestasDadas = 0;
                        }
                    }
                break;
                case "LosePregCerradas":
                    {
                        respuestasDadas++;
                        if (respuestasDadas == 3)
                        {
                            if (respuestasCorrectas == 1)
                            {
                                p1.Send("Win");
                            }
                            if (respuestasCorrectas == 2)
                            {
                                p1.Send("Win");
                                p2.Send("Win");
                            }
                            if (respuestasCorrectas == 3)
                            {
                                p1.Send("Win");
                                p2.Send("Win");
                                p3.Send("Win");
                            }
                            Console.WriteLine("Restarting game");
                            Broadcast("Restart");
                            Console.WriteLine("Broadcast Restart finished");
                            respuestasCorrectas = 0;
                            respuestasDadas = 0;
                        }
                        
                    }
                break;
                case "Lose":
                    {
                        respuestasDadas++;
                        respuestasMalas++;
                        if (respuestasMalas == 1)
                        {
                            difJ1 = message.GetInt(0);
                            j1 = player;
                        }
                        if (respuestasMalas == 2)
                        {
                            difJ2 = message.GetInt(0);
                            j2 = player;
                        }
                        if (respuestasMalas == 3)
                        {
                            difJ3 = message.GetInt(0);
                            j3 = player;
                        }
                        if (respuestasDadas == 3)
                        {
                            if (!respuestasCompletasEvaluadas)
                            {
                                if (respuestasCorrectas == 0)
                                {
                                    if ((difJ1 < difJ2) && (difJ1 < difJ3))
                                    {
                                        j1.Send("Win",2);
                                        idUsuario2 = j1.Id;
                                        if (difJ2 < difJ3)
                                        {
                                            j2.Send("Win",1);
                                            idUsuario1 = j2.Id;
                                            j3.Send("Lose",0);
                                            idUsuario0 = j3.Id;
                                        }
                                        else if (difJ2 > difJ3)
                                        {
                                            j3.Send("Win",1);
                                            idUsuario1 = j3.Id;
                                            j2.Send("Lose",0);
                                            idUsuario0 = j2.Id;
                                        }
                                        else if (difJ2 == difJ3)
                                        {
                                            if (numeroAleatoreo(1, random) == 1)
                                            {
                                                j2.Send("Win",1);
                                                idUsuario1 = j2.Id;
                                                j3.Send("Lose",0);
                                                idUsuario0 = j3.Id;
                                            }
                                            else
                                            {
                                                j3.Send("Win",1);
                                                idUsuario1 = j3.Id;
                                                j2.Send("Lose",0);
                                                idUsuario0 = j2.Id;
                                            }
                                        }
                                    }
                                    if ((difJ2 < difJ1) && (difJ2 < difJ3))
                                    {
                                        j2.Send("Win",2);
                                        idUsuario2 = j2.Id;
                                        if (difJ1 < difJ3)
                                        {
                                            j1.Send("Win",1);
                                            idUsuario1 = j1.Id;
                                            j3.Send("Lose",0);
                                            idUsuario0 = j3.Id;
                                        }
                                        else if (difJ1 > difJ3)
                                        {
                                            j3.Send("Win",1);
                                            idUsuario1 = j3.Id;
                                            j1.Send("Lose",0);
                                            idUsuario0 = j1.Id;
                                        }
                                        else if (difJ1 == difJ3)
                                        {
                                            if (numeroAleatoreo(1, random) == 1)
                                            {
                                                j1.Send("Win",1);
                                                idUsuario1 = j1.Id;
                                                j3.Send("Lose",0);
                                                idUsuario0 = j3.Id;
                                            }
                                            else
                                            {
                                                j3.Send("Win",1);
                                                idUsuario1 = j3.Id;
                                                j1.Send("Lose",0);
                                                idUsuario0 = j1.Id;
                                            }
                                        }
                                    }
                                    if ((difJ3 < difJ2) && (difJ3 < difJ1))
                                    {
                                        j3.Send("Win",2);
                                        idUsuario2 = j3.Id;
                                        if (difJ1 < difJ2)
                                        {
                                            j1.Send("Win",1);
                                            idUsuario1 = j1.Id;
                                            j2.Send("Lose",0);
                                            idUsuario0 = j2.Id;
                                        }
                                        else if (difJ1 > difJ2)
                                        {
                                            j2.Send("Win",1);
                                            idUsuario1 = j2.Id;
                                            j1.Send("Lose",0);
                                            idUsuario0 = j1.Id;
                                        }
                                        else if (difJ1 == difJ2)
                                        {
                                            if (numeroAleatoreo(1, random) == 1)
                                            {
                                                j1.Send("Win",1);
                                                idUsuario1 = j1.Id;
                                                j2.Send("Lose",0);
                                                idUsuario0 = j2.Id;
                                            }
                                            else
                                            {
                                                j2.Send("Win",1);
                                                idUsuario1 = j2.Id;
                                                j1.Send("Lose",0);
                                                idUsuario0 = j1.Id;
                                            }
                                        }
                                    }
                                    if ((difJ1 == difJ2) && (difJ2 == difJ3) && (difJ3 == difJ1))
                                    {
                                        Console.WriteLine("Pregunta abierta: Todas las respuestas recibidas son iguales, se eligirá ganador al azar");
                                        if (numeroAleatoreo(1, random) == 0)
                                        {
                                            j1.Send("Win",2);
                                            idUsuario2 = j1.Id;
                                            j2.Send("Win",1);
                                            idUsuario1 = j2.Id;
                                            j3.Send("Lose",0);
                                            idUsuario0 = j3.Id;
                                        }
                                        else
                                        {
                                            j2.Send("Win",2);
                                            idUsuario2 = j2.Id;
                                            j3.Send("Win",1);
                                            idUsuario1 = j3.Id;
                                            j1.Send("Lose",0);
                                            idUsuario0 = j1.Id;
                                        }
                                    }
                                }
                                if (respuestasCorrectas == 1)
                                {
                                    if (fase == 1)
                                    {
                                        p1.Send("Win",2);
                                        idUsuario2 = p1.Id;
                                        if (difJ1 < difJ2)
                                        {
                                            j1.Send("Win",1);
                                            idUsuario1 = j1.Id;
                                            j2.Send("Lose",0);
                                            idUsuario0 = j2.Id;
                                        }
                                        else if (difJ2 > difJ1)
                                        {
                                            j2.Send("Win",1);
                                            idUsuario1 = j2.Id;
                                            j1.Send("Lose",0);
                                            idUsuario0 = j1.Id;
                                        }
                                        else if (difJ1 == difJ2)
                                        {
                                            if (numeroAleatoreo(1, random) == 1)
                                            {
                                                j1.Send("Win",1);
                                                idUsuario1 = j1.Id;
                                                j2.Send("Lose",0);
                                                idUsuario0 = j2.Id;
                                            }
                                            else
                                            {
                                                j2.Send("Win",1);
                                                idUsuario1 = j2.Id;
                                                j1.Send("Lose",0);
                                                idUsuario0 = j1.Id;
                                            }
                                        }
                                    }
                                    if (fase == 2)
                                    {
                                        p1.Send("Win");
                                        j1.Send("Lose");
                                        j2.Send("Lose");
                                    }
                                }
                                if (respuestasCorrectas == 2)
                                {
                                    if (fase == 1)
                                    {
                                        p1.Send("Win",2);
                                        idUsuario2 = p1.Id;
                                        p2.Send("Win",1);
                                        idUsuario1 = p2.Id;
                                        j1.Send("Lose",0);
                                        idUsuario0 = j1.Id;
                                    }
                                    if (fase == 2)
                                    {
                                        p1.Send("Win");
                                        p2.Send("Lose");
                                        j1.Send("Lose");
                                    }
                                }
                                if (respuestasCorrectas == 3)
                                {
                                    if (fase == 1)
                                    {
                                        p1.Send("Win",2);
                                        idUsuario2 = p1.Id;
                                        p2.Send("Win",1);
                                        idUsuario1 = p2.Id;
                                        p3.Send("Lose",0);
                                        idUsuario0 = p3.Id;
                                    }
                                    if (fase == 2)
                                    {
                                        p1.Send("Win");
                                        p2.Send("Lose");
                                        p3.Send("Lose");
                                    }
                                }
                                respuestasCorrectas = 0;
                                respuestasDadas = 0;
                                respuestasMalas = 0;
                                Console.WriteLine("Restarting game");
                                Broadcast("Restart");
                                Console.WriteLine("Broadcast Restart finished");
                                respuestasCompletasEvaluadas = true;
                            }
                        }
                    }
                break;
                case "getID":
                    player.Send(""+player.Id);
                break;
                case "TerritorioSeleccionado":
                {
                    Broadcast("TerritorioSeleccionado", player.Id, message.GetInt(0));
                }
                break;
                case "EnviarOrden":
                {
                    Console.WriteLine("Enviando autor. para escoger territorios desocupado");
                    Broadcast("OrdenEleccion", idUsuario2, idUsuario1, idUsuario0);
                }
                break;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rango">
        /// the random number has to be a number between zero and "random"
        /// </param>
        /// <returns>
        /// returns the random number
        /// </returns>
        private static int numeroAleatoreo(int rango, Random numero)
        {
            int n = numero.Next(rango);
            return n;

        }
        /// <summary>
        /// This method is called when the server must sleep x seconds
        /// </summary>
        /// <param name="nSecs">
        /// "nSecs" tell the method how much (in seconds) the server must sleep
        /// </param>
        private static void WaitSeconds(double nSecs)
        {
            // Esperar los segundos indicados

            // Crear la cadena para convertir en TimeSpan
            string s = "0.00:00:" + nSecs.ToString().Replace(",", ".");
            TimeSpan ts = TimeSpan.Parse(s);

            // Añadirle la diferencia a la hora actual
            DateTime t1 = DateTime.Now.Add(ts);

            // Esta asignación solo es necesaria
            // si la comprobación se hace al principio del bucle
            DateTime t2 = DateTime.Now;

            // Mientras no haya pasado el tiempo indicado
            while (t2 < t1)
            {
                // Un respiro para el sitema
                // Asignar la hora actual
                t2 = DateTime.Now;
            }
        }

		Point debugPoint;
		// During development, it's very usefull to be able to cause certain events
		// to occur in your serverside code. If you create a public method with no
		// arguments and add a [DebugAction] attribute like we've down below, a button
		// will be added to the development server. 
		// Whenever you click the button, your code will run.
		[DebugAction("Stop", DebugAction.Icon.Stop)]
		public void StopNow() {
			Console.WriteLine("WARNING: STOPPING THE GAME...");
            jugador1.Disconnect();
            if (this.PlayerCount == 2)
            {
                jugador2.Disconnect();
            }
            else if (this.PlayerCount == 3)
            {
                jugador2.Disconnect();
                jugador3.Disconnect();
            }
		}

		// If you use the [DebugAction] attribute on a method with
		// two int arguments, the action will be triggered via the
		// debug view when you click the debug view on a running game.
		[DebugAction("Set Debug Point", DebugAction.Icon.Green)]
		public void SetDebugPoint(int x, int y) {
			debugPoint = new Point(x,y);
		}
	}
}
